package com.xhj.mybatis.scripting.xmltags;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * ExpressionEvaluator
 *
 * @author XJks
 * @description 表达式求值器，用于解析和计算 OGNL 表达式
 */
public class ExpressionEvaluator {

    /**
     * 评估表达式的布尔值结果
     *
     * @param expression      OGNL 表达式字符串
     * @param parameterObject 作为上下文的参数对象
     * @return 表达式的布尔值结果
     */
    public boolean evaluateBoolean(String expression, Object parameterObject) {
        // 通过 OgnlCache 获取表达式的计算结果
        Object value = OgnlCache.getValue(expression, parameterObject);
        // 如果结果是 Boolean 类型，直接返回其值
        if (value instanceof Boolean) {
            return (Boolean) value;
        }
        // 如果结果是数字类型，判断其是否不等于 0
        if (value instanceof Number) {
            return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0;
        }
        // 其他情况，只要结果不为 null 就认为为 true
        return value != null;
    }

    /**
     * 评估表达式的可迭代结果
     *
     * @param expression      OGNL 表达式字符串
     * @param parameterObject 作为上下文的参数对象
     * @return 表达式的可迭代结果
     * @throws RuntimeException 如果结果为 null 或不可迭代
     */
    public Iterable<?> evaluateIterable(String expression, Object parameterObject) {
        // 通过 OgnlCache 获取表达式的计算结果
        Object value = OgnlCache.getValue(expression, parameterObject);
        // 如果结果为 null，抛出异常
        if (value == null) {
            throw new RuntimeException("The expression '" + expression + "' evaluated to a null value.");
        }
        // 如果结果本身是 Iterable 类型，直接返回
        if (value instanceof Iterable) {
            return (Iterable<?>) value;
        }
        // 判断结果是否是数组类型， 如果结果是数组类型，由于数组可能是基本类型，不能直接用 Arrays.asList，需要手动转换
        if (value.getClass().isArray()) {
            // 获取数组长度
            int size = Array.getLength(value);
            // 创建一个列表用于存放数组元素
            List<Object> answer = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                // 逐个获取数组元素
                Object o = Array.get(value, i);
                // 添加到列表
                answer.add(o);
            }
            // 返回列表
            return answer;
        }
        // 如果结果是 Map 类型，返回其 entrySet（键值对集合）
        if (value instanceof Map) {
            return ((Map) value).entrySet();
        }
        // 其他情况，抛出异常，说明结果不可迭代
        throw new RuntimeException("Error evaluating expression '" + expression + "'.  Return value (" + value + ") was not iterable.");
    }

}
